﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace Beaker.Collections
{
	/// <summary>
	/// Extensions to and/or for the <see cref="IEnumerable{T}"/> interface.
	/// </summary>
	public static class EnumerableExtensions
	{
#if !NET4
		/// <summary>
		/// Converts the sequence of items into a NEW readonly list.
		/// </summary>
		/// <typeparam name="TItem">The type of the items in the list</typeparam>
		/// <param name="items">The items for in the list</param>
		/// <returns>A copy of the sequence as a read only list.</returns>
		/// <remarks>This method makes a NEW list, so changes to the original list will not influence the read only list.</remarks>
		public static IReadOnlyList<TItem> ToReadOnlyList<TItem>(this IEnumerable<TItem> items)
		{
			// make a new list
			var list = new List<TItem>(items ?? new TItem[0]);

			// the wrap in a readonly accessor
			return new ReadOnlyCollection<TItem>(list);
		}
#endif

		/// <summary>
		/// Execute the action on all items in the sequence during the enumeration of the sequence
		/// </summary>
		/// <typeparam name="TItem">The type of the items in the sequence.</typeparam>
		/// <param name="items">The sequence of items to process.</param>
		/// <param name="actionToDo">The action to execute on every item in the sequence.</param>
		/// <returns>The sequence as passed in to chain a next operation.</returns>
		public static IEnumerable<TItem> DoDeferred<TItem>(this IEnumerable<TItem> items, Action<TItem> actionToDo)
		{
			if (items == null)
				yield break;

			foreach (TItem item in items)
			{
				if (actionToDo != null)
					actionToDo(item);

				yield return item;
			}
		}

		/// <summary>
		/// Execute the action on all items in the sequence.
		/// </summary>
		/// <typeparam name="TItem">The type of the items in the sequence.</typeparam>
		/// <param name="items">The sequence of items to process.</param>
		/// <param name="actionToDo">The action to execute on every item in the sequence.</param>
		public static void Do<TItem>(this IEnumerable<TItem> items, Action<TItem> actionToDo)
		{
			if (items == null)
				return;

			if (actionToDo != null)
				foreach (TItem item in items)
					actionToDo(item);
		}
	}
}
